package com.functest.orm

import groovy.sql.Sql
import groovy.transform.ToString

import java.text.SimpleDateFormat

/**
 * Created with IntelliJ IDEA.
 * User: KovalevAS
 * Date: 28.06.13
 * Time: 14:28
 * To change this template use File | Settings | File Templates.
 */
class TestData {
    static {
        Class.forName('org.sqlite.JDBC');
    }
/*************DB*************/
    final static Sql ourDB
/*************test class*************/
    static class test_class {
        int first_field
        int second_field
        int one_to_many
    }
/*************StudentStatus*************/
    static enum StudentStatus {
        Graduate, Student, Expelled
    }
/*************Student class*************/
    @ToString(includeFields = true)

    static class Student_withLongId {
        Long id
        String firstName
        String lastName
        StudentStatus status
        String today
        //table: town
        String town
        //table: marks
        int first
        int second
        int third
        String average

    Student_withLongId(Long id, String firstName, String lastName, StudentStatus status) {
        this.id = id
        this.firstName = firstName
        this.lastName = lastName
        this.status = status
    }

    /* SingleDbTableMappers */
    static SingleDbTableMapper<Student_withLongId> student_mapper =
        new SingleDbTableMapper<Student_withLongId>(
                new MapperFields().with {
                    field('id')
                    field('firstName', 'first_name')
                    field('lastName')
                    field('status', 'status', MapperUtil.transform.stringEnum(StudentStatus),
                            MapperUtil.transformBack.stringEnum(StudentStatus))
                    delegate as MapperFields
                }
                , { TestData.ourDB }
                , 'student'
                , 'id'
                , Student_withLongId
        )

    /* Provider */
         static BaseProvider<Student_withLongId> provider = new BaseProvider<Student_withLongId>(Student_withLongId, [student_mapper])

        Student_withLongId(Map params) {
            for (Map.Entry entry in params.entrySet()) {
                if (entry.value != null) {
                    this."${entry.key }" = entry.value
                }
            }
        }
    }

    static class Student {
        /* Fields */
        //table: student
        int id
        String firstName
        String lastName
        StudentStatus status
        String today
        //table: town
        String town
        //table: marks
        int first
        int second
        int third
        String average
        String fullName

        Student() {}

        Student(int id, String firstName, String lastName, StudentStatus status) {
            this.id = id
            this.firstName = firstName
            this.lastName = lastName
            this.status = status
        }

        /* SingleDbTableMappers */
        static SingleDbTableMapper<Student> student_mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field('id')
                        field('firstName', 'first_name')
                        field('lastName')
                        field('status', 'status', MapperUtil.transform.stringEnum(StudentStatus),
                                MapperUtil.transformBack.stringEnum(StudentStatus))
                        delegate as MapperFields
                    }
                    , { TestData.ourDB }
                    , 'student'
                    , 'id'
                    , Student
            )

        /* Provider */
        static BaseProvider<Student> provider = new BaseProvider<Student>(Student, [student_mapper])


    }

/** ********************/
/*SingleDbTableMappers*/
/** ********************/
    static SingleDbTableMapper<Student> student_table_full_mapper
    static SingleDbTableMapper<Student> marks_table_multi_column_mapper
    static SingleDbTableMapper<Student> town_table_full_mapper
    static SingleDbTableMapper<Student> third_table_full_mapper
    static SingleDbTableMapper<Student> student_table_mapper_with_multicolumn_id_field
/** **************/
/*MapperBindings*/
/** **************/
    static MapperBinding first_mapper_binding
/** *****************/
/*MultiTableMappers*/
/** *****************/
    static MultiTableMapper<Student> multiTableMapper_without_bindings
    static MultiTableMapper<Student> multiTableMapper_with_bindings
/** ************/
/*BaseProviders*/
/** ************/
    static BaseProvider<Student> base_provider
/** ********************/
/*fields initialization*/
/** ********************/
    static {
        /*DB*/
        ourDB = Sql.newInstance('jdbc:sqlite::memory:', 'org.sqlite.SQLite')
        ourDB.with {
            execute("create table student (id int, first_name text, lastName text, status text)")
            execute("insert into student values(-1,'Petr','Petrov','Student')")
            execute("insert into student values(0,'Maria','Petrova','Student')")
            execute("insert into student values(2,'Ivan','Ivanov','Graduate')")
            execute("insert into student values(3,'Sidor','Sidorov','Student')")
            execute("insert into student values(4,'Looser L.','Looser','Expelled')")
            execute("insert into student values(5,'Alexandr',null,'Expelled')")
            execute("insert into student values(21474836475,'Julia','Sidorova','Graduate')")
        }
        ourDB.with {
            execute("create table town (town_id integer, town_name text)")
            execute("insert into town values(2, 'Moscow')")
            execute("insert into town values(3, 'Moscow')")
            execute("insert into town values(4, 'Orel')")
        }
        ourDB.with {
            //no imagination
            execute("create table marks (student_id int, first int, second int, third int)")
            execute("insert into marks values (2,  5,4,3)")
            execute("insert into marks values (3,  3,5,3)")
            execute("insert into marks values (4,  4,3,5)")
        }
        /*SingleDbTableMappers*/
        student_table_full_mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field('id')
                        field('today', [], { Field f, Map m ->
                                def date = new Date()
                                def sdf = new SimpleDateFormat("MM/dd/yyyy")
                            sdf.format(date)
                        } as Closure,
                        { Field f, def value ->
                            [today: Date.parse("MM/dd/yyyy", value as String)]
                        } as Closure)
                        field('firstName', 'first_name')
                        field('lastName')
                        field('status', 'status', MapperUtil.transform.stringEnum(StudentStatus),
                                MapperUtil.transformBack.stringEnum(StudentStatus))
                        delegate as MapperFields
                    }
                    , { TestData.ourDB }
                    , 'student'
                    , 'id'
                    , Student
            )

        marks_table_multi_column_mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field('id', 'student_id')
                        field('first')
                        field('second')
                        field('third')
                        field('average', ['first', 'second', 'third'],
                                {
                                    Field f, Map m ->
                                        ((m['first'].toString()) +
                                                (m['second'].toString()) +
                                                (m['third'].toString()))
                                } as Closure,
                                {
                                    Field f, def value ->
                                        def ch_arr = (value as String).toCharArray()
                                        [first: ch_arr[0], second: ch_arr[1], third: ch_arr[2]]
                                } as Closure
                        )
                        delegate as MapperFields
                    },
                    { TestData.ourDB },
                    'marks',
                    'id',
                    Student
            )

        town_table_full_mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field('id', 'town_id')
                        field('town', 'town_name')
                        delegate as MapperFields
                    }
                    , { TestData.ourDB }
                    , 'town'
                    , 'id'
                    , Student
            )

        third_table_full_mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field('id', 'student_id')
                        field('first')
                        field('second')
                        field('third')
                        delegate as MapperFields
                    }
                    , { TestData.ourDB }
                    , 'marks'
                    , 'id'
                    , Student
            )

        student_table_mapper_with_multicolumn_id_field =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with {
                        field ('fullName',
                                ['first_name', 'lastName'],
                                {
                                    Field f, Map m ->
                                        m['first_name'].toString() +
                                        '_' +
                                        m['lastName'].toString()
                                } as Closure,
                                {
                                    Field f, def value ->
                                        def res = (value as String).split('_')
                                        ['first_name': res.first(), 'lastName': res.last()]
                                } as Closure
                        )

                        delegate as MapperFields
                    }
                    , { TestData.ourDB}
                    , 'student'
                    , 'fullName'
                    , Student
            )

        /*MapperBindings*/
        first_mapper_binding =
            new MapperBinding(student_table_full_mapper)
        /*MultiTableMappers*/
        multiTableMapper_without_bindings =
            new MultiTableMapper<Student>(
                [student_table_full_mapper, town_table_full_mapper, third_table_full_mapper],
                Student,
                []
        )

        multiTableMapper_with_bindings =
            new MultiTableMapper<Student>(
                    [student_table_full_mapper, town_table_full_mapper, third_table_full_mapper],
                    Student,
                    []
            )
        /*BaseProviders*/
        base_provider =
            new BaseProvider<Student>(Student, multiTableMapper_without_bindings)
    }
}